package com.camus.verify.biz.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StopWatch;

import com.camus.verify.biz.MatchHandler;
import com.camus.verify.bo.MatchBO;
import com.camus.verify.entity.VerifyResult;
import com.camus.verify.entity.VerifyResultAp;
import com.camus.verify.entity.VerifyResultInvoice;
import com.camus.verify.entity.VerifyTask;
import com.camus.verify.entity.VerifyTaskAp;
import com.camus.verify.entity.VerifyTaskInvoice;
import com.camus.verify.enums.VerifyAssociatedTypeEnum;
import com.google.common.collect.Lists;

import cn.hutool.core.util.IdUtil;

public abstract class AbstractMatchHandler implements MatchHandler {
	
	public final Logger log = LoggerFactory.getLogger(getClass());
	public static ThreadLocal<StopWatch> timer = ThreadLocal.withInitial(() -> new StopWatch());

	protected MatchBO buildResultBO(final VerifyTask task, final List<VerifyTaskInvoice> invoiceList,
			final List<VerifyTaskAp> apList) {
		MatchBO bo = new MatchBO();
		bo.setTask(task);
		bo.setTaskApList(apList);
		bo.setTaskInvoiceList(invoiceList);

		// 生成编号
		String code = "HX" + IdUtil.getSnowflake().nextIdStr();
		// 生成核销结果主表
		VerifyResult result = buildVerifyResult(code, task);
		result.setSpec(invoiceList.get(0).getSpec());
		result.setPrice(invoiceList.get(0).getPrice());
		bo.setResult(result);
		// 生成核销结果明细表-台账表
		List<VerifyResultAp> resultApList = buildVerifyResultApList(result, apList);
		bo.setApList(resultApList);
		// 生成核销结果明细表-发票表
		List<VerifyResultInvoice> resultInvliceList = buildVerifyResultInvoiceList(result, invoiceList);
		bo.setInvoiceList(resultInvliceList);

		// 更新主表汇总明细的字段
		result.setVerifyAmtAp(
				resultApList.stream().map(VerifyResultAp::getVerifyAmt).reduce(BigDecimal.ZERO, BigDecimal::add));
		result.setVerifyQtyAp(
				resultApList.stream().map(VerifyResultAp::getVerifyQty).reduce(BigDecimal.ZERO, BigDecimal::add));
		result.setVerifyAmtInvoice(resultInvliceList.stream().map(VerifyResultInvoice::getVerifyAmt)
				.reduce(BigDecimal.ZERO, BigDecimal::add));
		result.setVerifyQtyInvoice(resultInvliceList.stream().map(VerifyResultInvoice::getVerifyQty)
				.reduce(BigDecimal.ZERO, BigDecimal::add));
		result.setVerifyAmtDiff(result.getVerifyAmtInvoice().subtract(result.getVerifyAmtAp()));
		if (apList.size() == 1) {
			result.setVerifyAssociatedType(invoiceList.size() == 1 ? VerifyAssociatedTypeEnum.One2One.getCode()
					: VerifyAssociatedTypeEnum.Many2One.getCode());
		} else {
			result.setVerifyAssociatedType(invoiceList.size() == 1 ? VerifyAssociatedTypeEnum.One2Many.getCode()
					: VerifyAssociatedTypeEnum.Many2Many.getCode());
		}
		return bo;
	}

	private List<VerifyResultInvoice> buildVerifyResultInvoiceList(final VerifyResult result,
			final List<VerifyTaskInvoice> paramList) {
		List<VerifyResultInvoice> list = Lists.newArrayList();
		for (VerifyTaskInvoice tmp : paramList) {
			list.add(buildVerifyResultInvoice(result, tmp));
		}
		return list;
	}

	private VerifyResultInvoice buildVerifyResultInvoice(final VerifyResult result, final VerifyTaskInvoice tmp) {
		VerifyResultInvoice dtl = new VerifyResultInvoice();
		dtl.setPkid(null);
		dtl.setSourceId(tmp.getPkid());
		dtl.setInvoiceId(tmp.getSourceId());
		dtl.setResultCode(result.getResultCode());
		dtl.setInvoiceNo(tmp.getInvoiceNo());
		dtl.setInvoiceCode(tmp.getInvoiceCode());
		dtl.setInvoiceSn(tmp.getInvoiceSn());
		dtl.setGoods(tmp.getGoods());
		dtl.setSpec(tmp.getSpec());
		dtl.setPrice(tmp.getPrice());
		dtl.setVerifyQty(tmp.getPendingVerifyQty());
		dtl.setVerifyAmt(tmp.getPendingVerifyAmt());
		// dtl.setAddedTime(LocalDateTime.now());
		// dtl.setLastModifiedTime(LocalDateTime.now());
		return dtl;
	}

	private List<VerifyResultAp> buildVerifyResultApList(final VerifyResult result,
			final List<VerifyTaskAp> paramList) {
		List<VerifyResultAp> list = Lists.newArrayList();
		for (VerifyTaskAp tmp : paramList) {
			list.add(buildVerifyResultAp(result, tmp));
		}
		return list;
	}

	private VerifyResultAp buildVerifyResultAp(final VerifyResult result, final VerifyTaskAp tmp) {
		VerifyResultAp dtl = new VerifyResultAp();
		dtl.setPkid(null);
		dtl.setSourceId(tmp.getPkid());
		dtl.setApgId(tmp.getSourceId());
		dtl.setResultCode(result.getResultCode());
		dtl.setPoCode(tmp.getPoCode());
		dtl.setPoItemId(tmp.getPoItemId());
		dtl.setPoDate(tmp.getPoDate());
		dtl.setPorCode(tmp.getPorCode());
		dtl.setPorItemId(tmp.getPorItemId());
		dtl.setPorDate(tmp.getPorDate());
		dtl.setGoods(tmp.getGoods());
		dtl.setSpec(tmp.getSpec());
		dtl.setPrice(tmp.getSettledPrice());
		dtl.setVerifyQty(tmp.getPendingVerifyQty());
		dtl.setVerifyAmt(tmp.getPendingVerifyAmt());
		// dtl.setAddedTime(LocalDateTime.now());
		// dtl.setLastModifiedTime(LocalDateTime.now());
		return dtl;
	}

	private VerifyResult buildVerifyResult(final String code, final VerifyTask task) {
		VerifyResult result = new VerifyResult();
		result.setResultCode(code);
		result.setLeName(task.getLeName());
		result.setTsTrName(task.getTsTrName());
		result.setTaskCode(task.getTaskCode());
		result.setVerifyDate(LocalDateTime.now());
		// result.setAddedTime(LocalDateTime.now());
		// result.setLastModifiedTime(LocalDateTime.now());
		return result;
	}

}
